package com.weavernorth.util.SearchFile;

import com.weavernorth.util.Logger4jUtil;
import org.apache.log4j.Logger;

import java.io.*;
import java.util.*;

/**
 * @Author: bruseewang
 * @Package: com.weavernorth.util.SearchFile
 * @date: 2021/8/23 11:26
 * @description: 在指定目录搜索文件名包含关键字的文件并返回路径
 */
public class SearchFileByName {

    public static FileOutputStream fos = null;
    public static int num = 0;
    public static void main(String[] args) {
        Logger log = Logger4jUtil.getLoggerByName("/Timmer/SalesTaskCreateFlowTimmer/");
//        List<File> files = searchFiles(new File("C:\\Users\\wangwenbin1\\Desktop"), "新建");
//        System.out.println("共找到:" + files.size() + "个文件");
//        for (File file : files) {
//            System.out.println(file.getAbsolutePath());
//        }
        long start = System.currentTimeMillis();
//        File file = new File("/usr/weaver/ecology/log");
//        File[] files = file.listFiles();
//        getFilesOfStack(files, "张三", "txt");
//        getFiles(files,"张三");
        traverseFolder("/usr/weaver/ecology/log/test");
        long finish = System.currentTimeMillis();
        long timeElapsed = finish - start;
        System.out.println("检索完成,耗时：" + timeElapsed / 1000 + "秒");
    }

    /***
     * 查询文件名包含关键字的文件
     * @param folder
     * @param keyword
     * @return
     */
    public static List<File> searchFiles(File folder, String keyword) {
        List<File> result = new ArrayList<File>();
        if (folder.isFile())
            result.add(folder);

        File[] subFolders = folder.listFiles(new FileFilter() {
            @Override
            public boolean accept(File file) {
                if (file.isDirectory()) {
                    return true;
                }
                if (file.getName().toLowerCase().contains(keyword)) {
                    return true;
                }
                return false;
            }
        });
        if (subFolders != null) {
            for (File file : subFolders) {
                if (file.isFile()) {
                    // 如果是文件则将文件添加到结果列表中
                    result.add(file);
                } else {
                    // 如果是文件夹，则递归调用本方法，然后把所有的文件加到结果列表中
                    result.addAll(searchFiles(file, keyword));
                }
            }
        }
        return result;
    }


    /***
     * 搜索文件内容包含关键字的文件-递归
     * 只查找文件大小<1G的文件
     * @param files
     * @param keyWords
     */
    public static void getFiles(File[] files, String keyWords) {
        FileInputStream fis = null;
        StringBuilder sb = null;
        try {
            for (File file : files) {
                if (file.isDirectory()) {
                    getFiles(file.listFiles(), keyWords);
                } else {
                    num++;
                    if (file.length() * 2 < Integer.MAX_VALUE) {
                        sb = new StringBuilder();
                        byte[] bytes = new byte[1024];
                        fis = new FileInputStream(file);
                        int len = 0;
                        while ((len = fis.read(bytes)) != -1) {
                            sb.append(new String(bytes, 0, len));
                        }
                        fis.close();
                        if (sb.indexOf(keyWords) >= 0) {
                            System.out.println(file.getAbsolutePath());
//                        fos.write((file.getAbsolutePath() + System.lineSeparator()).getBytes());
//                        fos.flush();
                        }
                        sb = null;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
//            Runtime run = Runtime.getRuntime();
//            System.out.println("最大内存：" + (run.maxMemory()/1024/1024));
//            System.out.println("已分配内存：" + (run.totalMemory()/1024/1024));
//            System.out.println("剩余内存：" + (run.freeMemory()/1024/1024));
//            long result=(run.maxMemory() - run.totalMemory() + run.freeMemory())/1024/1024;
//            System.out.println("最大可用内存：" + result);
        }
    }

    /***
     * 非递归遍历文件夹及文件
     * @param path
     */
    public static void traverseFolder(String path) {
        LinkedList<File> list = new LinkedList<File>();
        File file = new File(path);
        try {
            if (file.exists()) {
                File[] files = file.listFiles();

                for (File thisFile : files) {
                    if (thisFile.isDirectory()) {
                        list.add(thisFile);
                        continue;
                    }
                    System.out.println(thisFile.getName());
                }

            } else {
                System.out.println("该文件将夹为空！！！");
            }
            File tempFile;
            for (Iterator itr = list.iterator(); itr.hasNext(); ) {
                tempFile = list.removeFirst();
                for (File thisFile : tempFile.listFiles()) {
                    if (thisFile.isDirectory()) {
                        list.add(thisFile);
                        continue;
                    }
                    System.out.println(thisFile.getName());
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    /***
     * 递归遍历文件夹及文件
     * @param path
     */
    public static void traverseFolderByRecursion(String path) {

        File file = new File(path);
        if (file.exists()) {
            File[] files = file.listFiles();
            for (File thisFile : files) {
                if (thisFile.isDirectory()) {
                    traverseFolderByRecursion(thisFile.getAbsolutePath());
                } else {
                    System.out.println("路径："+thisFile.getAbsolutePath()+";文件名："+thisFile.getName());
                }
            }
        } else {
            System.out.println("该文件夹为空！");
        }
    }

    /***
     * 搜索文件内容包含关键字的文件-非递归
     * 只查找文件大小<1G的文件
     * JVM需要设置参数：-Xmx8g -Xms8g -Xmn4g -Xss128k
     * @param files
     * @param keyWords
     */
    public static void getFilesOfStack(File[] files, String keyWords, String fileType) {
        FileInputStream fis = null;
        StringBuilder sb = null;
        Stack<File[]> stack = new Stack<File[]>();
        stack.push(files); // 入栈
        System.out.println("入栈总数(指定路径下的文件夹及文件夹数量)：" + files.length);
        try {
            while (!stack.isEmpty()) {
                File[] pop = stack.pop();
//                System.out.println("栈对象中文件数量："+pop.length);
                for (File file : pop) {
                    if (file.isDirectory()) {
                        stack.push(file.listFiles());
                    } else {
                        num++;
                        //只查找固定的文件类型或所有的文件
//                        System.out.println(file.getName() + "是否可读：" + file.canRead());
                        if (file.getName().endsWith(fileType)||fileType==null) {
                            //System.out.println("当前文件数量"+num);
                            //StringBuilder的最大值为Integer.MAX_VALUE(2147483647),由于StringBuilder自动2倍扩容，所以超出界限会导致内存溢出
                            if ((file.length() * 2) < Integer.MAX_VALUE) {
//                            System.out.println("文件名：" + file.getAbsolutePath() + "的文件大小：" + file.length() + "字节");
                                sb = new StringBuilder();
                                byte[] bytes = new byte[1024];
                                fis = new FileInputStream(file);
                                int len = 0;
                                while ((len = fis.read(bytes)) != -1) {
                                    sb.append(new String(bytes, 0, len));
                                }
                                fis.close();
                                if (sb.indexOf(keyWords) >= 0) {
                                    System.out.println("文件路径：" + file.getAbsolutePath());
                                }
                            }
                        }

                    }

                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            Runtime run = Runtime.getRuntime();
            System.out.println("最大内存：" + (run.maxMemory() / 1024 / 1024) + "M");
            System.out.println("已分配内存：" + (run.totalMemory() / 1024 / 1024) + "M");
            System.out.println("剩余内存：" + (run.freeMemory() / 1024 / 1024) + "M");
            long result = (run.maxMemory() - run.totalMemory() + run.freeMemory()) / 1024 / 1024;
            System.out.println("最大可用内存：" + result + "M");
        }
    }


}
